﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;

namespace Epic.Core
{
    public static class EmitUtility
    {
#pragma warning disable 1591

        public static CustomAttributeBuilder ToBuilder(this CustomAttributeData target)
        {
            var namedFieldArguments = target.NamedArguments.Where(a => a.MemberInfo is FieldInfo).ToArray();
            var namedPropertieArguments = target.NamedArguments.Where(a => a.MemberInfo is PropertyInfo).ToArray();

            return new CustomAttributeBuilder(
                target.Constructor,
                target.ConstructorArguments.Select(a => a.Value).ToArray(),
                namedPropertieArguments.Select(a => a.MemberInfo).Cast<PropertyInfo>().ToArray(),
                namedPropertieArguments.Select(a => a.TypedValue.Value).ToArray(),
                namedFieldArguments.Select(a => a.MemberInfo).Cast<FieldInfo>().ToArray(),
                namedFieldArguments.Select(a => a.TypedValue.Value).ToArray());
        }

        #region GetCustomAttributeBuilders
        public static CustomAttributeBuilder[] GetCustomAttributeBuilders(this Assembly target)
        {
            return CustomAttributeData.GetCustomAttributes(target).Select(a => a.ToBuilder()).ToArray();
        }
        public static CustomAttributeBuilder[] GetCustomAttributeBuilders(this Module target)
        {
            return CustomAttributeData.GetCustomAttributes(target).Select(a => a.ToBuilder()).ToArray();
        }
        public static CustomAttributeBuilder[] GetCustomAttributeBuilders(this MemberInfo target)
        {
            return CustomAttributeData.GetCustomAttributes(target).Select(a => a.ToBuilder()).ToArray();
        }
        public static CustomAttributeBuilder[] GetCustomAttributeBuilders(this ParameterInfo target)
        {
            return CustomAttributeData.GetCustomAttributes(target).Select(a => a.ToBuilder()).ToArray();
        }
        #endregion

        #region MakeDynamicAssemblyStub
        public static AssemblyBuilder MakeDynamicAssemblyStub(this AppDomain appDomain, Assembly reference, string assemblyName)
        {
            return appDomain.MakeDynamicAssemblyStub(reference, new AssemblyName(assemblyName));
        }
        public static AssemblyBuilder MakeDynamicAssemblyStub(this AppDomain appDomain, Assembly reference, AssemblyName assemblyName)
        {
            return appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run, reference.GetCustomAttributeBuilders());
        }
        #endregion
    }
}
